package com.iman.common.util;

import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import org.codehaus.jackson.JsonEncoding;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.type.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;

import com.iman.common.Constants;

/**
 * JSON工具里，主要使用Jackson来进行jon化。
 * <p>
 * 对于pojo有一点要求，主要是因为hibernate在生成对象的时候，如果不想序列化，需要增加@JsonIgnore的生命在get方法上
 * 
 *         <p>
 *         Date : 20101116
 */
public class JsonUtil {
    public static final Logger                logger       = LoggerFactory.getLogger(JsonUtil.class);

    private static ObjectMapper objectMapper = new ObjectMapper();
    private static JsonFactory  jsonFactory  = new JsonFactory();
    static {
        SerializationConfig cfg = objectMapper.getSerializationConfig();
        /**
         * // First, defaults:
         * assertTrue(cfg.isEnabled(SerializationConfig.Feature
         * .USE_ANNOTATIONS));
         * assertTrue(cfg.isEnabled(SerializationConfig.Feature
         * .AUTO_DETECT_GETTERS));
         * assertTrue(cfg.isEnabled(SerializationConfig.Feature
         * .CAN_OVERRIDE_ACCESS_MODIFIERS));
         * 
         * assertTrue(cfg.isEnabled(SerializationConfig.Feature.
         * WRITE_NULL_PROPERTIES));
         * assertTrue(cfg.isEnabled(SerializationConfig.
         * Feature.WRITE_DATES_AS_TIMESTAMPS));
         * 
         * assertFalse(cfg.isEnabled(SerializationConfig.Feature.INDENT_OUTPUT))
         * ; assertFalse(cfg.isEnabled(SerializationConfig.Feature.
         * USE_STATIC_TYPING));
         * 
         * // since 1.3: assertTrue(cfg.isEnabled(SerializationConfig.Feature.
         * AUTO_DETECT_IS_GETTERS)); // since 1.4
         * 
         * assertTrue(cfg.isEnabled(SerializationConfig.Feature.
         * FAIL_ON_EMPTY_BEANS)); // since 1.5
         * assertTrue(cfg.isEnabled(SerializationConfig
         * .Feature.DEFAULT_VIEW_INCLUSION));
         */
        // cfg.setDateFormat(dateFormat);
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        df.setTimeZone(TimeZone.getTimeZone("CMT"));
        //cfg.withDateFormat(df);//不用这个方法，因为这个输出timestamp格式，下面输出的是yyyy-mm-dd格式
        cfg.setDateFormat(df);
    }

    public static <T> Object fromJson(String jsonAsString, Class<T> pojoClass) throws JsonMappingException, JsonParseException, IOException {
        return objectMapper.readValue(jsonAsString, pojoClass);
    }

    public static <T> Object fromJson(String jsonAsString, TypeReference tr) throws JsonMappingException, JsonParseException, IOException {
        return objectMapper.readValue(jsonAsString, tr);
    }

    public static String toJson(Object pojo) {
        return toJson(pojo, false);
    };

    public static void write(Object pojo, OutputStream os) throws JsonMappingException, JsonGenerationException, IOException {
        objectMapper.writeValue(os, pojo);
    }

    protected static final JsonEncoding getJsonEncoding(MediaType contentType) {
        if (contentType != null && contentType.getCharSet() != null) {
            Charset charset = contentType.getCharSet();
            for (JsonEncoding encoding : JsonEncoding.values()) {
                if (charset.name().equals(encoding.getJavaName())) {
                    return encoding;
                }
            }
        }
        return JsonEncoding.UTF8;
    }

    public static String toJson(Object pojo, boolean prettyPrint) {
        StringWriter sw = new StringWriter();
        try {
            JsonGenerator jg = jsonFactory.createJsonGenerator(sw);
            if (prettyPrint) {
                jg.useDefaultPrettyPrinter();
            }
            objectMapper.writeValue(jg, pojo);
            String s = sw.toString();
            logger.debug(s);
            return s;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String getJsonFromList(List list) {
        StringBuilder sb = new StringBuilder("{success:true,");
        sb.append(Constants.TOTALCOUNT);
        sb.append(":");
        sb.append(list.size());
        sb.append(",");
        sb.append(Constants.RESULTS);
        sb.append(":");
        sb.append(toJson(list, false));
        sb.append("}");
        return sb.toString();
    };

    public static String toString(JsonNode node) {
        try {
            JsonFactory jsonFactory = new JsonFactory();
            StringWriter sw = new StringWriter();
            JsonGenerator generator = jsonFactory.createJsonGenerator(sw);
            generator.writeTree(node);
            return sw.toString();
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
    };

    public static void write(JsonNode node, OutputStream out) {
        try {
            JsonFactory jsonFactory = new JsonFactory();
            JsonGenerator generator = jsonFactory.createJsonGenerator(out, JsonEncoding.UTF8);
            generator.writeTree(node);
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
    };

    public static final ObjectMapper getMapper() {
        return objectMapper;
    }
    
    @SuppressWarnings("unchecked")
    public static final Map getJsonMap(Object o){
        Object[] data = new Object[1];
        data[0] = o;
        return CollectionUtils.newMap(Constants.RESULTS, data);
    }
}
